<script lang="ts">
    import Icon from "../Common/Icons/Icon.svelte";
    import { Value } from "../Common/Value";
    import { Dropdown } from "../Dropdown";
    import { useFormItemContext } from "../FormItem/FormItem.svelte";
    import type { TagConfig } from "../TagGroup";
    import { Tree } from "../Tree";
    import type { NodeKeyType, TreeInstanceProps, TreeNode } from "../Tree/Tree";
    import { TreeCheckMod } from "../Tree/Tree.svelte";
    import { useClassList } from "../utils/useClassList";
    import type { TreeSelectProps } from "./TreeSelect";

    let { multi, value = $bindable(multi ? [] : ""), ...props }: TreeSelectProps = $props();
    const ctx = useFormItemContext();
    let text = $state<any>();
    let keyField = props.keyField || "id";
    let titleField = props.titleField || "title";
    let checkedKeys = $state<NodeKeyType[]>([]);
    let selectedKey = $state<NodeKeyType>();

    const align = props.align ?? "bottomLeft";
    let tree: TreeInstanceProps | undefined;
    const mode: TreeCheckMod = props.mode ?? TreeCheckMod.HALF;

    const classList = $derived(
        useClassList(props, "cm-tree-select", {
            "cm-tree-select-disabled": props.disabled,
            [`cm-tree-select-${props.size}`]: props.size,
        }),
    );

    const onSelect = (data: any) => {
        if (!multi) {
            value = data[keyField];
            props.onchange?.(data[keyField]);
            ctx?.onFieldChange?.();
        }
    };

    const onTreeChange = (ids: NodeKeyType[] | NodeKeyType) => {
        value = ids;
        props.onchange?.(ids);
        ctx?.onFieldChange?.();
    };

    const onClear = () => {
        const ret: NodeKeyType | NodeKeyType[] = multi ? [] : "";
        value = ret;
        props.onchange?.(ret);
        ctx?.onFieldChange?.();
    };

    const onValueClose = (item: TagConfig, e: any) => {
        const v = value as NodeKeyType[];
        v.splice(v.indexOf(item.id), 1);
        value = [...v];
        checkedKeys = [...v];
        setTimeout(() => {
            const all = getChecked();
            value = [...all];
            props.onchange?.([...all]);
            ctx?.onFieldChange?.();
        });
    };

    const getChecked = () => {
        const all = tree?.getCheckedKeys(mode);
        return all || [];
    };

    $effect(() => {
        checkedKeys = value as NodeKeyType[];
    });

    $effect(() => {
        let vals = value;
        props.data;
        if (multi) {
            setTimeout(() => {
                const all: any[] =
                    tree?.getChecked(mode).map((item: TreeNode) => {
                        return {
                            id: item[keyField || "id"],
                            title: item[titleField || "title"],
                        };
                    }) || [];
                text = all;
            });
        } else {
            setTimeout(() => {
                const data: TreeNode | undefined = tree?.getNode(vals as NodeKeyType);
                if (data) {
                    text = { title: data[titleField || "title"] };
                } else {
                    text = { title: "" };
                }
            });
        }
    });
</script>

<div class={classList} style={props.style} tabIndex="0">
    <Dropdown transfer={props.transfer} fixWidth {align} disabled={props.disabled} trigger="click">
        {#snippet menu()}
            <div class="cm-tree-select-wrap">
                <Tree
                    data={props.data}
                    checkable={multi}
                    onnodeselect={onSelect}
                    onchange={onTreeChange}
                    bind:this={tree}
                    bind:value={checkedKeys}
                    bind:selectedKey
                    checkRelation={props.checkRelation}
                />
            </div>
        {/snippet}
        <Value
            {text}
            {multi}
            showMax={props.showMax}
            disabled={props.disabled}
            showMore={props.showMore}
            valueClosable={props.valueClosable}
            clearable={props.clearable}
            placeholder={props.placeholder}
            {onClear}
            prepend={props.prepend}
            size={props.size}
            onClose={onValueClose}
        >
            {#snippet icon()}
                <Icon icon="chevronDown" />
            {/snippet}
        </Value>
    </Dropdown>
</div>
